# -*- coding: utf-8 -*-
# FileName:     ZKeyShow.py
# time:         22/11/25 025 下午 9:27
# Author:       Zhou Hang
# Description:  I don't want to write
import sys

from pynput import keyboard
from PyQt5.QtCore import Qt, QThread, pyqtSignal
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QMenu

from src.custom_control.key_label import KeyLabel
from src.custom_control.movable_widget import MovableWidget
from data.key_dict import keyboard_key_dict
from src.utils.zqueue import ZQueue


class ZKeyShow(MovableWidget):
    def __init__(self):
        super(ZKeyShow, self).__init__()
        self.setFixedSize(800, 800)
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        self.setWindowIcon(QIcon('../resource/keyboard.png'))

        # 用一个队列存放近期按下的按键，每一项都是KeyLabel
        self.pushed_key_queue = ZQueue(7)
        self.pushed_key_queue.push(self.gen_key_label("快开始吧!"))

    def gen_key_label(self, key):
        """生成一个按键Label"""
        new_key_lbl = KeyLabel(f'{key}', self)
        new_key_lbl.move((self.width() - new_key_lbl.width()) // 2 - 150,
                         (self.height() - new_key_lbl.height()) // 2 + 300)
        return new_key_lbl

    def add_key_press(self, key: str):
        """接收APP传递来的键码，使用QLabel在界面上显示"""
        # 往上挪来腾出位置给新的
        for lbl in self.pushed_key_queue.for_each_label():
            lbl.upward_move()

        print(f'{key} 被按下')
        self.pushed_key_queue.push(self.gen_key_label(key))
        self.pushed_key_queue.get_latest().show()

    def contextMenuEvent(self, event):
        """右击触发菜单，有一个退出功能"""
        menu = QMenu(self)
        fixAction = menu.addAction('固定')
        quitAction = menu.addAction("退出")
        action = menu.exec_(self.mapToGlobal(event.pos()))
        if action == quitAction:
            self.close()
        elif action == fixAction:
            self.setWindowOpacity(0.1)
            self.cur_label.setWindowOpacity(1)
            self.setAttribute(Qt.WA_TranslucentBackground)


class KeyDetect(QThread):
    signal = pyqtSignal(str)

    def __init__(self):
        super(KeyDetect, self).__init__()
        self.record_key = []

    def run(self) -> None:
        with keyboard.Listener(on_press=self.on_press,
                               on_release=self.on_release) as listener:
            listener.join()

    def on_press(self, key):
        """按下按键时执行。"""
        try:
            # print(f'{key.char} 被按下 key_type:{type(key)}')
            # self.signal.emit(key.char)
            key_code = key.char  # 这里的key_code不一定是原本的值，应该先恢复一下
        except AttributeError:
            # print(f'特殊按键 {key} 被按下 key_type:{type(key)}')
            # self.signal.emit(str(key.name))
            key_code = key.name
        if key_code is not None:
            key_combine_code = str(bytes(key_code, encoding="utf-8")).lstrip('b')  # 这里强烈需要理解
        else:  # pynput库无法处理ctrl+，/。的情况，这里不得不这样
            return
        if keyboard_key_dict.get(key_combine_code, None) is not None:
            key_code = keyboard_key_dict[key_combine_code][-1]
        if key_code not in self.record_key:  # 长按不重复加入
            self.record_key.append(key_code)

    def on_release(self, key):
        """松开按键时执行。"""
        # print('{0} released'.format(key))
        if len(self.record_key) > 1:
            # 是组合键
            print(self.record_key)
            self.signal.emit('+'.join(self.record_key))
            self.record_key.clear()  # 将record_key全部删除
        else:
            try:
                try:
                    self.record_key.remove(f'{key.char}')
                    self.signal.emit(f'{key.char}')
                except AttributeError:
                    self.record_key.remove(f'{key.name}')
                    self.signal.emit(f'{key.name}')
            except ValueError:
                pass
            except TypeError:  # pynput库无法处理ctrl+，/。的情况
                pass
        if key == keyboard.Key.esc:
            return False  # Stop listener


class APP:
    def __init__(self):
        self.app = ZKeyShow()
        # 设置默认位置
        desktop = QApplication.desktop()
        x = (desktop.width() - self.app.width()) // 2 - 300
        y = (desktop.height() - self.app.height()) // 2
        self.app.move(x, y)
        self.app.show()
        self.key_detect_t = KeyDetect()
        self.key_detect_t.signal.connect(self.key_show)
        self.key_detect_t.start()

    def key_show(self, data: str):
        self.app.add_key_press(data)


def main():
    app = QApplication(sys.argv)
    view = APP()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()
